package com.ndp.fb.walle.business.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import com.ndp.fb.rdb.model.adpublishcondition.UserConnectionPage;
import com.ndp.fb.rdb.model.productmanage.ProductManageCondition;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.fastjson.JSON;
import com.esotericsoftware.minlog.Log;
import com.ndp.ec.core.ProductManageService;
import com.ndp.ec.core.UserService;
import com.ndp.fb.constant.CommonConstants;
import com.ndp.fb.enums.PlatForm;
import com.ndp.fb.enums.publish.BillingEvent;
import com.ndp.fb.enums.publish.OptimizationGoal;
import com.ndp.fb.model.business.bo.targetingspec.Age;
import com.ndp.fb.model.business.bo.targetingspec.Platform;
import com.ndp.fb.model.business.vo.cache.result.PriceLimitBo;
import com.ndp.fb.rdb.api.AccountInstagramActRdbService;
import com.ndp.fb.rdb.api.AdPublishConditionDetailRdbService;
import com.ndp.fb.rdb.api.AdPublishConditionRdbService;
import com.ndp.fb.rdb.api.FbUserRdbService;
import com.ndp.fb.rdb.api.ProductManageRdbService;
import com.ndp.fb.rdb.api.UserRdbServices;
import com.ndp.fb.rdb.api.VpiCountryInfoRdbService;
import com.ndp.fb.rdb.api.VpiInfoRdbService;
import com.ndp.fb.rdb.model.AccountInstagramAct;
import com.ndp.fb.rdb.model.ConnectionObject;
import com.ndp.fb.rdb.model.EntrustAccount;
import com.ndp.fb.rdb.model.EntrustAccountExt;
import com.ndp.fb.rdb.model.FbUser;
import com.ndp.fb.rdb.model.Pager;
import com.ndp.fb.rdb.model.User;
import com.ndp.fb.rdb.model.UserExt;
import com.ndp.fb.rdb.model.VpiCountryInfo;
import com.ndp.fb.rdb.model.VpiInfo;
import com.ndp.fb.rdb.model.adpublishcondition.AdPublishCondition;
import com.ndp.fb.rdb.model.adpublishcondition.AdPublishConditionAccount;
import com.ndp.fb.rdb.model.adpublishcondition.AdPublishConditionDetail;
import com.ndp.fb.rdb.model.adpublishcondition.AdPublishConditionResult;
import com.ndp.fb.rdb.model.adpublishcondition.Region;
import com.ndp.fb.rdb.model.adpublishcondition.RegionAndPrice;
import com.ndp.fb.rdb.model.productmanage.ProductManage;
import com.ndp.fb.redis.api.RedisDistributedLockService;
import com.ndp.fb.redis.api.VpiInfoRedisService;
import com.ndp.fb.util.ListUtil;
import com.ndp.fb.util.StringUtil;
import com.ndp.fb.walle.business.AdPublishAppAccountCPAService;
import com.ndp.fb.walle.business.AdPublishConditionService;
import com.ndp.fb.walle.business.EntrustAccountService;
import com.ndp.fb.walle.model.bo.productconfiguration.result.ProductConfigurationBo;
import com.ndp.fb.walle.model.vo.adpublishcondition.param.AdPublishConditionDetailParam;
import com.ndp.fb.walle.model.vo.adpublishcondition.param.RegionAndPriceParam;
import com.ndp.fb.walle.model.vo.adpublishcondition.result.AdPublishConditionDetailResult;
import com.ndp.fb.walle.model.vo.adpublishcondition.result.RegionAndPriceObject;
import com.ndp.fb.walle.model.vo.adpublishcondition.result.RegionAndPriceResult;
import com.ndp.fb.walle.model.vo.connectionobject.result.ConnectionObjectExtVo;
import com.ndp.fb.walle.util.SortListUtil;

/**
 * Created by Evan on 2015/3/24 16:06.
 */
@Component
public class AdPublishConditionServiceImpl implements AdPublishConditionService {

    private final Logger logger = LoggerFactory.getLogger(getClass());

    @Reference
    private AdPublishConditionRdbService adPublishConditionRdbService;

    @Reference
    AdPublishConditionDetailRdbService adPublishConditionDetailRdbService;

    @Reference
    private VpiInfoRdbService vpiInfoRdbService;

    @Reference
    private VpiCountryInfoRdbService vpiCountryInfoRdbService;

    @Reference
    private FbUserRdbService fbUserRdbService;

    @Reference
    private VpiInfoRedisService vpiInfoRedisService;

    @Reference
    private UserRdbServices userRdbServices;

    @Reference
    private AccountInstagramActRdbService accountInstagramActRdbService;

    @Autowired
    private EntrustAccountService entrustAccountService;

    @Autowired
    private RedisDistributedLockService redisDistributedLockService;

    @Reference
    private ProductManageRdbService productManageRdbService;

    @Reference
    private ProductManageService productManageService;
    @Autowired
    private AdPublishAppAccountCPAService adPublishAppAccountCPAService;
    @Reference
    private UserService userService;
    @Override
    public Pager<AdPublishConditionResult> findAdPublishConditionWithPager(String userId, String name, Long orgId, Integer firstResult, Integer sizeNo) {
        //定义个临时变量 用来存放 查出来的所有需要放到投放控制列表中显示的
//        List<AdPublishConditionResult> result = new ArrayList<>();

//        List<AdPublishConditionResult> adPublishConditions = adPublishConditionRdbService.findAdPublishConditionWithPager(userId, name, orgId);
//        List<String> inConditionList = new ArrayList<>();
//        if(ListUtil.isNotEmpty(adPublishConditions))
//        {
//            for(AdPublishConditionResult adPublishCondition : adPublishConditions)
//            {
//                inConditionList.add(adPublishCondition.getConnObjId() + String.valueOf(adPublishCondition.getProdCfgId()));
//                result.add(adPublishCondition);
//            }
//        }
//        List<String> inProductManageList = new ArrayList<>();
//        Map<String, ProductManage> productManageMap = new HashMap<>();
//        List<ProductManage> productManages = productManageRdbService.findByUserIdAndName(orgId, name);
//        if(ListUtil.isNotEmpty(productManages))
//        {
//            for(ProductManage productManage : productManages)
//            {
//                String prodCfgKey;
//                PlatForm platForm =  PlatForm.getPlatForm(productManage.getProdPlatform());
//                prodCfgKey = platForm.getKey().toString();
//                inProductManageList.add(productManage.getProdId() + prodCfgKey);
//                productManageMap.put(productManage.getProdId() + prodCfgKey, productManage);
//            }
//        }
//        inConditionList.retainAll(inProductManageList);  //这一步之后 inConditionList变成了交集
//        inProductManageList.removeAll(inConditionList);  //这一步之后 剩余的产品是之前没出现在投放控制中， 需要追加到前台让用户可设置
//        if(ListUtil.isNotEmpty(inProductManageList))
//        {
//            AdPublishConditionResult productManageResult;
//            for(String productManageId : inProductManageList)
//            {
//                productManageResult = new AdPublishConditionResult();
//                ProductManage pm = productManageMap.get(productManageId);
//                if(pm != null && StringUtil.isNotEmpty(pm.getProdName()) && StringUtil.isNotEmpty(pm.getProdPlatform()))
//                {
//                    productManageResult.setConnObjId(pm.getProdId());
//                    productManageResult.setStatus(0);
//                    productManageResult.setOperationStatus(0);
//                    productManageResult.setConnObjName(pm.getProdName());
//                    productManageResult.setProdCfgName(pm.getProdPlatform());
//                    productManageResult.setProductType(CommonConstants.OUTLINK);
//                    PlatForm platForm =  PlatForm.getPlatForm(pm.getProdPlatform());
//                    productManageResult.setProdCfgType(platForm.getKey());
//                    productManageResult.setProdCfgId(platForm.getKey().longValue());
//
//                    result.add(productManageResult);
//                }
//
//            }
//        }
//        //排序  1、打开的放前面 2、然后按产品名 字母排
//        if(ListUtil.isEmpty(result))
//            return null;
//        List<AdPublishConditionResult> adPublishConditionResultList = orderAdPublishCondition(result);
//        Pager<AdPublishConditionResult> pager = new Pager<>();
//        List<AdPublishConditionResult> pagerResult = new ArrayList<>();
//        if(adPublishConditionResultList.size()>(firstResult + sizeNo)){
//            pagerResult.addAll(adPublishConditionResultList.subList(firstResult, firstResult + sizeNo));
//        }else{
//            pagerResult.addAll(adPublishConditionResultList.subList(firstResult, adPublishConditionResultList.size()));
//        }


        Pager<ProductManageCondition> byUserIdAndName = productManageRdbService.findByUserIdAndName(orgId,userId, name, firstResult, sizeNo);
        List<ProductManageCondition> resultList = byUserIdAndName.getResultList();

        List<AdPublishConditionResult> collect = resultList.stream().map(pm -> {
            AdPublishConditionResult productManageResult = new AdPublishConditionResult();
            productManageResult.setId(pm.getConditionId()); //投放控制id
            productManageResult.setConnObjId(pm.getProdId());
            productManageResult.setStatus(pm.getStatus());
            productManageResult.setOperationStatus(pm.getOperationStatus());
            productManageResult.setConnObjName(pm.getProdName());
            productManageResult.setProdCfgName(pm.getProdPlatform());
            productManageResult.setProductType(CommonConstants.OUTLINK);
            PlatForm platForm = PlatForm.getPlatForm(pm.getProdPlatform());
            productManageResult.setProdCfgType(platForm.getKey());
            productManageResult.setProdCfgId(platForm.getKey().longValue());
            return productManageResult;
        }).collect(Collectors.toList());

        Pager resultPager = new Pager();
        resultPager.setTotalSize(byUserIdAndName.getTotalSize());
        resultPager.setPageIndex(byUserIdAndName.getPageIndex());
        resultPager.setPageSize(sizeNo);
        resultPager.setResultList(collect);
        return resultPager;
    }


    @Override
    public AdPublishCondition findAdPublishConditionById(Long id) {
        return adPublishConditionRdbService.findById(id);
    }

    @Override
    public AdPublishCondition updateStatus(String userId, Long id, int status) {
        if(redisDistributedLockService.tryLock(CommonConstants.AD_PUBLISH_CONDITION_UPDATE_STATUS)){
            try{
                adPublishConditionRdbService.updateStatus(userId, id, status == 0 ? false : true);
            }catch(Exception ex){
                Log.error(ex.getMessage(),ex);
            }finally {
                redisDistributedLockService.unLock(CommonConstants.AD_PUBLISH_CONDITION_UPDATE_STATUS);
            }
        }
        return adPublishConditionRdbService.findById(id);
    }

    @Override
    public void updateDetail(AdPublishConditionDetailParam param, String userId) {
        //一、更新主表 修改时间
        adPublishConditionRdbService.updateTimeById(param.getConditionId(), new Date(), new Date().getTime());
        //二、更新detail表
        AdPublishConditionDetail detail = new AdPublishConditionDetail();
        detail.setConditionId(param.getConditionId());
        detail.setConnObjSimpleName(param.getConnObjSimpleName());
        detail.setPageId(param.getPageId());
        detail.setPlatform(param.getPlatform());
        detail.setAge(param.getAge());
        detail.setSex(param.getSex());
        //处理PriceLimit
        List<PriceLimitBo> priceLimits = parsePriceLimit(param.getPriceLimit());

        detail.setPriceLimit(JSON.toJSONString(priceLimits));
        adPublishConditionRdbService.updateDetail(detail);
        //三、更新地区单价表
        RegionAndPriceParam regionAndPriceParam = JSON.parseObject(param.getRegionAndPrices(), RegionAndPriceParam.class);
        if (regionAndPriceParam != null) {
            List<RegionAndPrice> forVpi = new ArrayList<>();
            List<RegionAndPrice> forDb;
            if (regionAndPriceParam.getGlobal() != null) {
                RegionAndPrice globalRegionAndPrice = JSON.parseObject(regionAndPriceParam.getGlobal(), RegionAndPrice.class);
                globalRegionAndPrice.setConditionId(param.getConditionId());
                globalRegionAndPrice.setInclude(1);
                forVpi.add(globalRegionAndPrice);
                forDb = new ArrayList<>();
                forDb.add(globalRegionAndPrice);
                if (regionAndPriceParam.getExclude() != null) {
                    List<RegionAndPrice> excludeList = JSON.parseArray(regionAndPriceParam.getExclude(), RegionAndPrice.class);
                    {
                        if (ListUtil.isNotEmpty(excludeList)) {
                            forDb.addAll(excludeList);
                        }
                    }
                }
            } else {
                forDb = new ArrayList<>();
                addIncludeRegion(regionAndPriceParam, forVpi, forDb);
                if (regionAndPriceParam.getExclude() != null) {
                    List<RegionAndPrice> excludeList = JSON.parseArray(regionAndPriceParam.getExclude(), RegionAndPrice.class);
                    {
                        if (ListUtil.isNotEmpty(excludeList)) {
                            forDb.addAll(excludeList);
                        }
                    }
                }
            }

            adPublishConditionRdbService.updateRegionAndPrice(forDb, param.getConditionId());
            saveOrUpdateVpi(param, userId, forVpi);
        }
        //四、更新账号CPA表 不允许前台更新CPA表
        List<AdPublishConditionAccount> accountList = JSON.parseArray(param.getAccounts(), AdPublishConditionAccount.class);
        if (ListUtil.isNotEmpty(accountList)) {
            adPublishConditionRdbService.updateAccount(accountList, param.getConditionId());
        }
    }

    private void addIncludeRegion(RegionAndPriceParam regionAndPriceParam, List<RegionAndPrice> forVpi, List<RegionAndPrice> forDb) {
        if (regionAndPriceParam.getInclude() != null) {
            List<RegionAndPrice> includeList = JSON.parseArray(regionAndPriceParam.getInclude(), RegionAndPrice.class);
            {
                if (ListUtil.isNotEmpty(includeList)) {
                    forDb.addAll(includeList);
                    forVpi.addAll(includeList);
                }
            }
        }
    }

    private List<PriceLimitBo> parsePriceLimit(Map<String, Long> priceLimitM) {
        List<PriceLimitBo> priceLimits = new ArrayList<>();
        PriceLimitBo priceLimitBo;
        for (Map.Entry<String, Long> temp : priceLimitM.entrySet()){
            switch (temp.getKey())
            {
                case "a_i":
                    //应用安装量_展示次数
                    priceLimitBo = new PriceLimitBo(OptimizationGoal.APP_INSTALLS.toString(), BillingEvent.IMPRESSIONS.toString(), temp.getValue());
                    priceLimits.add(priceLimitBo);
                    break;
                case "a_a":
                    //应用安装量_应用安装
                    priceLimitBo = new PriceLimitBo(OptimizationGoal.APP_INSTALLS.toString(), BillingEvent.APP_INSTALLS.toString(), temp.getValue());
                    priceLimits.add(priceLimitBo);
                    break;
                case "c_i":
                    //链接点击量_展示次数
                    priceLimitBo = new PriceLimitBo(OptimizationGoal.LINK_CLICKS.toString(), BillingEvent.IMPRESSIONS.toString(), temp.getValue());
                    priceLimits.add(priceLimitBo);
                    break;
                case "c_c":
                    //链接点击量_链接点击量
                    priceLimitBo = new PriceLimitBo(OptimizationGoal.LINK_CLICKS.toString(), BillingEvent.LINK_CLICKS.toString(), temp.getValue());
                    priceLimits.add(priceLimitBo);
                    break;
                case "i_i":
                    //展示次数_展示次数
                    priceLimitBo = new PriceLimitBo(OptimizationGoal.IMPRESSIONS.toString(), BillingEvent.IMPRESSIONS.toString(), temp.getValue());
                    priceLimits.add(priceLimitBo);
                    break;
                case "r_i":
                    //单日独立覆盖_展示次数
                    priceLimitBo = new PriceLimitBo(OptimizationGoal.REACH.toString(), BillingEvent.IMPRESSIONS.toString(), temp.getValue());
                    priceLimits.add(priceLimitBo);
                    break;
                case "o_i":
                    //单日独立覆盖_展示次数
                    priceLimitBo = new PriceLimitBo(OptimizationGoal.OFFSITE_CONVERSIONS.toString(), BillingEvent.IMPRESSIONS.toString(), temp.getValue());
                    priceLimits.add(priceLimitBo);
                    break;
            }
        }
        return priceLimits;
    }


    /**
     * 插入优化单价设置表
     * 1、 某应用 配置 单价 有数据 则更新主表update_time 在查找地区有的不做操作，没有的国家新增
     * 2、 某应用 配置 单价 没有数据 则save主表 再save所有国家
     */
    private void saveOrUpdateVpi(AdPublishConditionDetailParam param, String userId, List<RegionAndPrice> regionAndPriceList) {
        VpiCountryInfo vpiCountryInfo = null;
        VpiInfo vpiInfo;
        for (RegionAndPrice regionAndPrice : regionAndPriceList) {
            if (regionAndPrice == null || regionAndPrice.getPrice() == null) {
                logger.info("AdPublishConditionServiceImpl saveOrUpdateVpi(): 国家地区有空元素" + regionAndPrice.getRegion());
                continue;
            }
            Integer price = (int) (regionAndPrice.getPrice() * 1000 / 10); //已经修复 assign to evan .  结果不对。  fixed 2015-08-24 double转int
            if (regionAndPrice.getType() != null && CommonConstants.GLOBAL.equals(regionAndPrice.getType())) {
                //全球  删除已有的 应用 配置 再新增一个全球的
                vpiInfo = vpiInfoRdbService.findUnionByCondition(userId, param.getConnObjId(), param.getProdCfgName(), price, CommonConstants.GLOBAL);
                if (vpiInfo != null) {
                    vpiInfoRdbService.updateUpdateTimeById(vpiInfo.getId(), new Date());
                } else {
                    vpiInfoRdbService.deleteVpiInfoAndVpiCountryInfo(userId, param.getConnObjId(), param.getProdCfgName());
                    vpiInfo = new VpiInfo();
                    vpiInfo.setCreateTime(new Date());
                    vpiInfo.setFbConnectionObjectId(param.getConnObjId());
                    vpiInfo.setConnectionObjectName(param.getConnObjName());
                    vpiInfo.setPlatform(param.getProdCfgName());
                    vpiInfo.setUserId(userId);
                    vpiInfo.setVpi(price);
                    vpiInfo.setRemark("new"); //备注  新增到vpi那边去
                    Long vpiInfoId = vpiInfoRdbService.save(vpiInfo);
                    vpiCountryInfo = new VpiCountryInfo();
                    vpiCountryInfo.setVpiInfoId(vpiInfoId);
                    vpiCountryInfo.setCountryCode(CommonConstants.GLOBAL);
                    vpiCountryInfo.setCountryName(CommonConstants.GLOBAL);
                    vpiCountryInfoRdbService.save(vpiCountryInfo);
                }
                vpiInfoRedisService.saveCache(param.getConnObjId().toString(), param.getProdCfgId() + CommonConstants.GLOBAL, vpiInfo);
            } else {
                List<Region> regions = JSON.parseArray(regionAndPrice.getRegion(), Region.class);
                vpiInfo = vpiInfoRdbService.findByCondition(userId, param.getConnObjId(), param.getProdCfgName(), price);
                if (vpiInfo != null) {
                    vpiInfoRdbService.updateUpdateTimeById(vpiInfo.getId(), new Date());
                    saveVpiCountryInfo(param, regions, vpiInfo);
                } else {
                    vpiInfo = new VpiInfo();
                    vpiInfo.setCreateTime(new Date());
                    vpiInfo.setFbConnectionObjectId(param.getConnObjId());
                    vpiInfo.setConnectionObjectName(param.getConnObjName());
                    vpiInfo.setPlatform(param.getProdCfgName());
                    vpiInfo.setUserId(userId);
                    vpiInfo.setVpi(price);
                    vpiInfo.setRemark("new"); //备注  新增到vpi那边去
                    Long vpiInfoId = vpiInfoRdbService.save(vpiInfo);
                    vpiInfo.setId(vpiInfoId);
                    saveVpiCountryInfo(param, regions, vpiInfo);
                }
            }
        }
    }

    /**
     * vpi countryinfo save
     */
    private void saveVpiCountryInfo(AdPublishConditionDetailParam param, List<Region> regions, VpiInfo info) {
        if (ListUtil.isNotEmpty(regions)) {
            //Evan 2015-04-27 存redis
            for (Region region : regions) {
                VpiCountryInfo vpiCountryInfo = vpiCountryInfoRdbService.findByVpiInfoIdAndCountryCode(info.getId(), region.getCountryCode());
                if (vpiCountryInfo == null) {
                    vpiCountryInfo = new VpiCountryInfo();
                    vpiCountryInfo.setVpiInfoId(info.getId());
                    vpiCountryInfo.setCountryCode(region.getCountryCode());
                    vpiCountryInfo.setCountryName(region.getName());
                    vpiCountryInfoRdbService.save(vpiCountryInfo);
                }
                vpiInfoRedisService.saveCache(param.getConnObjId().toString(), param.getProdCfgId() + region.getCountryCode(), info);
            }
        }
    }

    @Override
    public Long saveDetail(AdPublishConditionDetailParam param, String userId) {
        //一、保存主表
        AdPublishCondition adPublishCondition = new AdPublishCondition();
        adPublishCondition.setUserId(userId);
        adPublishCondition.setFbConnectionObjectId(param.getConnObjId());
        adPublishCondition.setConnObjName(param.getConnObjName());
        adPublishCondition.setProdCfgId(param.getProdCfgId());
        adPublishCondition.setProdCfgName(param.getProdCfgName());
        if(StringUtil.isNotEmpty(param.getProductType()))
            adPublishCondition.setProductType(param.getProductType());
        adPublishCondition.setStatus(false);
        adPublishCondition.setOperationStatus(1);
        adPublishCondition.setCreateTime(new Date());
        adPublishCondition.setCreateUtcTime(new Date().getTime());
        Long conditionId = adPublishConditionRdbService.saveAdPublishCondition(adPublishCondition);
        if (conditionId != null) {
            //二、保存detail表
            AdPublishConditionDetail detail = new AdPublishConditionDetail();
            detail.setConditionId(conditionId);
            detail.setPageId(param.getPageId());
            detail.setPlatform(param.getPlatform());
            detail.setSex(param.getSex());
            detail.setAge(param.getAge());
            //处理PriceLimit
            List<PriceLimitBo> priceLimits = parsePriceLimit(param.getPriceLimit());
            detail.setPriceLimit(JSON.toJSONString(priceLimits));
            detail.setConnObjSimpleName(param.getConnObjSimpleName());
            adPublishConditionRdbService.saveAdPublishConditionDetail(detail);
            //三、保存地区单价表
            RegionAndPriceParam regionAndPriceParam = JSON.parseObject(param.getRegionAndPrices(), RegionAndPriceParam.class);
            if (regionAndPriceParam != null) {
                List<RegionAndPrice> forVpi = new ArrayList<>();
                List<RegionAndPrice> forDb;
                if (regionAndPriceParam.getGlobal() != null) {
                    RegionAndPrice globalRegionAndPrice = JSON.parseObject(regionAndPriceParam.getGlobal(), RegionAndPrice.class);
                    globalRegionAndPrice.setConditionId(conditionId);
                    globalRegionAndPrice.setInclude(1);
                    forVpi.add(globalRegionAndPrice);
                    forDb = new ArrayList<>();
                    forDb.add(globalRegionAndPrice);
                    if (regionAndPriceParam.getExclude() != null) {
                        List<RegionAndPrice> excludeList = JSON.parseArray(regionAndPriceParam.getExclude(), RegionAndPrice.class);
                        {
                            if (ListUtil.isNotEmpty(excludeList)) {
                                forDb.addAll(excludeList);
                            }
                        }
                    }
                } else {
                    forDb = new ArrayList<>();
                    addIncludeRegion(regionAndPriceParam, forVpi, forDb);
                    if (regionAndPriceParam.getExclude() != null) {
                        List<RegionAndPrice> excludeList = JSON.parseArray(regionAndPriceParam.getExclude(), RegionAndPrice.class);
                        {
                            if (ListUtil.isNotEmpty(excludeList)) {
                                forDb.addAll(excludeList);
                            }
                        }
                    }
                }

                adPublishConditionRdbService.batchSaveRegionAndPrice(forDb, conditionId);
                saveOrUpdateVpi(param, userId, forVpi);
            }

            //四、更新账号CPA表
            List<AdPublishConditionAccount> accountList = JSON.parseArray(param.getAccounts(), AdPublishConditionAccount.class);
            if (ListUtil.isNotEmpty(accountList)) {
                adPublishConditionRdbService.batchSaveAccount(accountList, conditionId);
            }
        }
        return conditionId;
    }

    @Override
    public AdPublishConditionDetail findDetailById(String userId, Long connObjId, Long prodCfgId) {
        return adPublishConditionDetailRdbService.findDetailById(userId, connObjId, prodCfgId);
    }

    @Override
    public AdPublishConditionDetail findDetailByConditionId(Long conditionId) {
        return adPublishConditionDetailRdbService.findDetailByConditionId(conditionId);
    }

    @Override
    public List<AdPublishConditionAccount> findAdPublishConditionAccount(Long conditionId,String userId) {
        FbUser fbUser = fbUserRdbService.getFbUserByUserId(userId);
        return adPublishConditionRdbService.findAdPublishConditionAccount(conditionId, fbUser.getFbUserId());
    }

    @Override
    public List<EntrustAccount> findAllowedAccounts(String userId, Long connObjId, Long prodCfgId) {
        //产品管理允许发布的广告账号
        List<EntrustAccount> entrustAccountByAdmins = adPublishConditionRdbService.findAllowedAccounts(userId, connObjId, prodCfgId);

        //判断是否为本地新增产品
        List<ProductManage> productManages = productManageService.findByProductId(connObjId);
        List<EntrustAccountExt> entrustAccountByLocals;
        if (!CollectionUtils.isEmpty(productManages)){
            entrustAccountByLocals = entrustAccountService.findEntrustAccountsByUserId(userId);
        } else {
            entrustAccountByLocals = entrustAccountService.findEntrustAccountsByfbConnectionObjectIdAndUserId(connObjId, userId);
        }

        List<EntrustAccount> allowedAccounts = new ArrayList<EntrustAccount>();
        for (EntrustAccount entrustAccountByAdmin :entrustAccountByAdmins){
            for(EntrustAccount entrustAccountByLocal :entrustAccountByLocals){
                if(entrustAccountByAdmin.getFbAccountId().equals(entrustAccountByLocal.getFbAccountId())){
                    /**
                     * set 账号是否支持 Instagram 广告
                     */
                    List<AccountInstagramAct> accountInstagramActs = accountInstagramActRdbService.queryInsActByAccount(entrustAccountByAdmin.getFbAccountId());
                    if(ListUtil.isEmpty(accountInstagramActs)){
                        entrustAccountByAdmin.setSupportInstagramAd(false);
                    }else{
                        entrustAccountByAdmin.setSupportInstagramAd(true);
                        entrustAccountByAdmin.setFirstSupportInsAct(accountInstagramActs.get(0).getInsAccountId());
                    }
                    allowedAccounts.add(entrustAccountByAdmin);
                }
            }
        }
        return allowedAccounts;
    }

    @Override
    public List<RegionAndPrice> findRegionAndPrice(Long conditionId) {
        return adPublishConditionRdbService.findRegionAndPrice(conditionId);
    }

    @Override
    public List<ConnectionObject> findByTypeAndUserId(int type, String userId) throws Exception
    {
        return adPublishConditionRdbService.findByTypeAndUserId(type, userId);
//        List<ConnectionObjectBo> boList = new ArrayList<>();
//        List<ConnectionObject> connectionObjectList = adPublishConditionRdbService.findByTypeAndUserId(type, userId);
//        if(ListUtil.isNotEmpty(connectionObjectList))
//        {
//            ConnectionObjectBo bo;
//            for (ConnectionObject connectionObject : connectionObjectList) {
//                bo = new ConnectionObjectBo();
//                BeanUtils.copyProperties(bo, connectionObject);
//                boList.add(bo);
//            }
//        }
//        return boList;
    }

    /**
     * 投放控制所有结果 排序  1打开的排前面 2 名称字母排
     */
    private List<AdPublishConditionResult> orderAdPublishCondition(List<AdPublishConditionResult> adPublishConditionResults)
    {
        List<AdPublishConditionResult> result = new ArrayList<>();
        List<AdPublishConditionResult> needOrderList = new ArrayList<>();
        for(AdPublishConditionResult adPublishConditionResult : adPublishConditionResults)
        {
            if(adPublishConditionResult.getStatus() == 1)
            {
                result.add(adPublishConditionResult);
            }
            else
            {
                needOrderList.add(adPublishConditionResult);
            }
        }
        SortListUtil.sort(needOrderList, "connObjName", null);
        result.addAll(needOrderList);
        return result;
    }

    /**
     * 查找投放控制打开的外链产品
     */
    @Override
    public List<ConnectionObjectExtVo> findOpenedOutlinkByUserIdAndOrgId(String userId, Long orgId)
    {
        List<ConnectionObjectExtVo> vos = new ArrayList<>();
        List<AdPublishCondition> outlinks = adPublishConditionRdbService.findOpenedOutlinkByUserIdAndOrgId(userId, orgId);
        if(ListUtil.isEmpty(outlinks))
            return vos;
        ConnectionObjectExtVo vo;
        ProductConfigurationBo prodCfgBo;
        List<ProductConfigurationBo> productConfigurations;
        Map<Long, ConnectionObjectExtVo> connectionObjectM = new HashMap<>();
        for(AdPublishCondition adPublishCondition : outlinks)
        {
            vo = connectionObjectM.get(adPublishCondition.getFbConnectionObjectId());
            if (null == vo){
                vo = new ConnectionObjectExtVo();
                vo.setId(adPublishCondition.getId());
                vo.setFbConnectionObjectId(adPublishCondition.getFbConnectionObjectId());
                vo.setName(adPublishCondition.getConnObjName());
                vo.setProductType(adPublishCondition.getProductType());

                //应用对应的配置
                productConfigurations = new ArrayList<>();
                vo.setProductConfigurations(productConfigurations);

                connectionObjectM.put(adPublishCondition.getFbConnectionObjectId(), vo);
            }

            prodCfgBo = new ProductConfigurationBo();
            prodCfgBo.setPlatform(adPublishCondition.getProdCfgName());
            if(StringUtil.isEmpty(adPublishCondition.getProdCfgName()))
                continue;
            Long prodCfgId;
            switch (adPublishCondition.getProdCfgName())
            {
                case "itunes":
                    prodCfgId = 1L;
                    break;
                case "itunes_ipad":
                    prodCfgId = 2L;
                    break;
                case "google_play":
                    prodCfgId = 3L;
                    break;
                default:
                    prodCfgId = 0L;
            }
            prodCfgBo.setId(prodCfgId);

            vo.getProductConfigurations().add(prodCfgBo);
        }

        vos.addAll(connectionObjectM.values());
        return vos;
    }

    @Override
    public List<ConnectionObject> findOutlinkByOrgId(Long orgId)
    {
        List<ConnectionObject> bos = new ArrayList<>();
        List<ProductManage> productManages = productManageRdbService.findByOrgId(orgId);
        if(ListUtil.isEmpty(productManages))
            return bos;
        List<Long> pIds = new ArrayList<>();
        ConnectionObject bo;
        for(ProductManage productManage : productManages)
        {
            if (pIds.contains(productManage.getProdId())){
                //过滤重复应用
                continue;
            }

            pIds.add(productManage.getProdId());
            bo = new ConnectionObject();
            bo.setId(productManage.getId());
            bo.setFbConnectionObjectId(productManage.getProdId());
            bo.setName(productManage.getProdName());
            bo.setProductType(CommonConstants.OUTLINK);
            bos.add(bo);
        }
        return bos;
    }


	@Override
	public AdPublishConditionDetail findDetailByConnObjIdPlatForm(String userId, Long connObjId, String platform) {
		return adPublishConditionRdbService.findDetailByConnObjIdPlatForm(userId, connObjId, platform);
	}

    @Override
    public Map<String, Object> processHistoryDatas() {
        Map<String, Object> results = new HashMap<>();
        //查询所有发布条件
        List<Long> ids = new ArrayList<>();
        //39 147 152 153 253
        ids.add(39L);
        ids.add(147L);
        ids.add(152L);
        ids.add(153L);
        ids.add(253L);
        List<AdPublishCondition> adPublishConditions = adPublishConditionRdbService.findByIds(ids);
        if (CollectionUtils.isEmpty(adPublishConditions)){
            results.put("totalCount", 0);
            return results;
        }
        User user;
        List<String> copyUsers;
        List<Long> failedIds = new ArrayList<>();
        for (AdPublishCondition adPublishCondition : adPublishConditions){
            try {
                user = userRdbServices.getUserByTicket(adPublishCondition.getUserId());

                copyUsers = new ArrayList<>();
                if ("outlink".equals(adPublishCondition.getProductType())){
                    //外链获取该公司下有投放控制权限的用户
                    List<UserExt> userExts = userRdbServices.getAllUserExtsByOrgId(user.getOrgId());
                    for (UserExt userExt : userExts){
                        List<String> roles = Arrays.asList(userExt.getRoleId().split("\\|"));
                        if (roles.contains("1") || roles.contains("2") || roles.contains("4")|| roles.contains("5")|| roles.contains("11")){
                            copyUsers.add(userExt.getTicket());
                        }
                    }
                } else {
                    //查询该发布条件对应公司下，具有改应用权限的用户，将发布条件复制给这些用户
                    List<User> users = userRdbServices.findByOrgIdAndConnectionOnjectId(user.getOrgId(), adPublishCondition.getFbConnectionObjectId());
                    for (User cuser : users){
                        copyUsers.add(cuser.getTicket());
                    }
                }

                if (CollectionUtils.isEmpty(copyUsers)){
                    continue;
                }

                AdPublishConditionDetail adPublishConditionDetail = adPublishConditionDetailRdbService.findDetailByConditionId(adPublishCondition.getId());
                List<AdPublishConditionAccount> adPublishConditionAccounts = adPublishConditionRdbService.findAdPublishConditionAccountByConditionId(adPublishCondition.getId());
                List<RegionAndPrice> regionAndPrices = adPublishConditionRdbService.findRegionAndPrice(adPublishCondition.getId());
                String ofUser = adPublishCondition.getUserId();
                for (String copyUser : copyUsers){
                    if (copyUser.equals(ofUser)){
                        //不用给发布条件本身的用户（即原来的管理员）重复复制一份
                        continue;
                    }

                    AdPublishCondition uAdPublishCondition =
                            adPublishConditionRdbService.findAdPublishCondition(copyUser, adPublishCondition.getFbConnectionObjectId(), adPublishCondition.getProdCfgId());
                    Long conditionId;
                    if (null == uAdPublishCondition){
                        adPublishCondition.setUserId(copyUser);
                        //复制发布条件
                        conditionId = adPublishConditionRdbService.saveAdPublishCondition(adPublishCondition);
                    } else {
                        conditionId = uAdPublishCondition.getId();
                    }

                    AdPublishConditionDetail uadPublishConditionDetail = adPublishConditionDetailRdbService.findDetailByConditionId(conditionId);
                    if (null == uadPublishConditionDetail){
                        //复制发布条件详情
                        adPublishConditionDetail.setConditionId(conditionId);
                        adPublishConditionRdbService.saveAdPublishConditionDetail(adPublishConditionDetail);
                    }

                    List<AdPublishConditionAccount> uadPublishConditionAccounts = adPublishConditionRdbService.findAdPublishConditionAccountByConditionId(conditionId);
                    if (CollectionUtils.isEmpty(uadPublishConditionAccounts)){
                        if (!CollectionUtils.isEmpty(adPublishConditionAccounts)){
                            //复制发布条件账号
                            for (AdPublishConditionAccount adPublishConditionAccount : adPublishConditionAccounts){
                                adPublishConditionAccount.setConditionId(conditionId);
                            }
                            adPublishConditionRdbService.batchSaveAccount(adPublishConditionAccounts, conditionId);
                        }
                    }

                    List<RegionAndPrice> uregionAndPrices = adPublishConditionRdbService.findRegionAndPrice(conditionId);
                    if (CollectionUtils.isEmpty(uregionAndPrices)){
                        if (!CollectionUtils.isEmpty(regionAndPrices)){
                            //复制发布条件地区
                            for (RegionAndPrice regionAndPrice : regionAndPrices){
                                regionAndPrice.setConditionId(conditionId);
                            }
                            adPublishConditionRdbService.batchSaveRegionAndPrice(regionAndPrices, conditionId);
                        }
                    }

                }
            } catch (Exception e){
                failedIds.add(adPublishCondition.getId());
            }
        }

        results.put("failedIds", failedIds);
        results.put("totalCount", adPublishConditions.size());
        return results;
    }


	@Override
	public AdPublishConditionDetailResult getAdPublishConditionDetailResult(Long conditionId) {
		 AdPublishCondition con = this.findAdPublishConditionById(conditionId);
         return this.getAdPublishConditionDetailResult(con);
	}
	private AdPublishConditionDetailResult getAdPublishConditionDetailResult(AdPublishCondition con) {
		AdPublishConditionDetailResult data = null;
		if (con != null) {
            data = new AdPublishConditionDetailResult();
            data.setConditionId(con.getId());
            data.setConnObjId(con.getFbConnectionObjectId());
            data.setProdCfgId(con.getProdCfgId());
            AdPublishConditionDetail detail = this.findDetailByConditionId(con.getId());
            data.setPageId(detail.getPageId());
            if (StringUtil.isEmpty(detail.getPlatform())) {
                List<Platform> platformList = new ArrayList<>();
                Platform p = new Platform();
                if (con.getProdCfgName() != null && "itunes".equals(con.getProdCfgName()))
                    p.setType(1);
                else if (con.getProdCfgName() != null && "itunes_ipad".equals(con.getProdCfgName()))
                    p.setType(3);
                else if (con.getProdCfgName() != null && "google_play".equals(con.getProdCfgName()))
                    p.setType(2);
                else
                    p.setType(1);
                p.setUserOS(new ArrayList<String>());
                p.setUserDevice(new ArrayList<String>());
                platformList.add(p);
                data.setPlatform(platformList);
            } else {
                data.setPlatform(JSON.parseArray(detail.getPlatform(), Platform.class));
            }

            data.setConnObjSimpleName(StringUtil.isEmpty(detail.getConnObjSimpleName()) ? "" : detail.getConnObjSimpleName());
            data.setAge(JSON.parseObject(detail.getAge(), Age.class));
            data.setSex(detail.getSex());
            //将数据库中的pricelimit转为前端可识别格式
            Map<String, Long> priceLimit = parsePriceLimit(detail.getPriceLimit());
            data.setPriceLimit(priceLimit);
            data.setRegionAndPrices(transferRegionAndPriceObject(this.findRegionAndPrice(con.getId())));
            //在载入的时候判断当前账号是否还有权限
            data.setAccounts(this.findAdPublishConditionAccount(con.getId(),con.getUserId()));
            Set<Long> accountIds = new HashSet<>();
            //覆盖掉前端配置的是否支持CPA,在这去个重
            if (!CollectionUtils.isEmpty(data.getAccounts())) {
            	AdPublishConditionAccount ad = null;
            	int size = data.getAccounts().size();
                for (int i = size-1;i>=0;i--) {
                	ad = data.getAccounts().get(i);
                	if(!accountIds.contains(ad.getFbAccountId())){
                		accountIds.add(ad.getFbAccountId());
                        ad.setIsSupportCPA(adPublishAppAccountCPAService.isSupportCPA(ad.getFbAccountId(), con.getProdCfgId(), con.getFbConnectionObjectId()));
                	}else{
                		data.getAccounts().remove(i);
                	}
                }
            }

        }
        return data;
	}
	private Map<String, Long> parsePriceLimit(String priceLimit) {
        List<PriceLimitBo> priceLimits = JSON.parseArray(priceLimit, PriceLimitBo.class);
        Map<String, Long> priceLimitM = new HashMap<>();
        for (PriceLimitBo temp : priceLimits){
            if (OptimizationGoal.APP_INSTALLS == OptimizationGoal.parse(temp.getOptimizationGoal())){
                //优化方式:应用安装量
                if (BillingEvent.IMPRESSIONS == BillingEvent.parse(temp.getBillingEvent())){
                    //付费方式：展示次数
                    priceLimitM.put("a_i", temp.getBidAmountTop());
                } else if (BillingEvent.APP_INSTALLS == BillingEvent.parse(temp.getBillingEvent())){
                    //付费方式：应用安装
                    priceLimitM.put("a_a", temp.getBidAmountTop());
                } else {
                    ;
                }
            } else if (OptimizationGoal.LINK_CLICKS == OptimizationGoal.parse(temp.getOptimizationGoal())){
                //优化方式:链接点击量
                if (BillingEvent.IMPRESSIONS == BillingEvent.parse(temp.getBillingEvent())){
                    //付费方式：展示次数
                    priceLimitM.put("c_i", temp.getBidAmountTop());
                } else if (BillingEvent.LINK_CLICKS == BillingEvent.parse(temp.getBillingEvent())){
                    //付费方式：链接点击量
                    priceLimitM.put("c_c", temp.getBidAmountTop());
                } else {
                    ;
                }
            } else if (OptimizationGoal.IMPRESSIONS == OptimizationGoal.parse(temp.getOptimizationGoal())) {
                //优化方式:展示次数
                if (BillingEvent.IMPRESSIONS == BillingEvent.parse(temp.getBillingEvent()))
                {
                    //付费方式：展示次数
                    priceLimitM.put("i_i", temp.getBidAmountTop());
                }
            } else if (OptimizationGoal.REACH == OptimizationGoal.parse(temp.getOptimizationGoal())) {
                //优化方式:单日独立覆盖
                if (BillingEvent.IMPRESSIONS == BillingEvent.parse(temp.getBillingEvent()))
                {
                    //付费方式：展示次数
                    priceLimitM.put("r_i", temp.getBidAmountTop());
                }
            } else if (OptimizationGoal.OFFSITE_CONVERSIONS == OptimizationGoal.parse(temp.getOptimizationGoal())) {
                //优化方式:单日独立覆盖
                if (BillingEvent.IMPRESSIONS == BillingEvent.parse(temp.getBillingEvent()))
                {
                    //付费方式：展示次数
                    priceLimitM.put("o_i", temp.getBidAmountTop());
                }
            }
        }
        return priceLimitM;
    }
	private RegionAndPriceObject transferRegionAndPriceObject(List<RegionAndPrice> bos) {
        RegionAndPriceObject o = new RegionAndPriceObject();
        List<RegionAndPriceResult> includeList = new ArrayList<>();
        List<RegionAndPriceResult> excludeList = new ArrayList<>();
        RegionAndPriceResult result;
        if (ListUtil.isNotEmpty(bos)) {
            for (RegionAndPrice bo : bos) {
                if (bo.getInclude() != null) {
                    if (bo.getInclude() == 0) {
                        result = new RegionAndPriceResult();
                        result.setConditionId(bo.getConditionId());
                        result.setId(bo.getId());
                        //result.setVpi(bo.getVpi());
                        result.setType(bo.getType());
                        result.setInclude(bo.getInclude());
                        result.setRegion(JSON.parseArray(bo.getRegion(), Region.class));
                        excludeList.add(result);
                    } else if (bo.getInclude() == 1 && bo.getType() != null && CommonConstants.GLOBAL.equals(bo.getType())) {
                        result = new RegionAndPriceResult();
                        result.setConditionId(bo.getConditionId());
                        result.setId(bo.getId());
                        result.setPrice(bo.getPrice());
                        result.setType(bo.getType());
                        result.setInclude(bo.getInclude());
                        o.setGlobal(result);
                    } else if (bo.getInclude() == 1 && bo.getType() != null && !CommonConstants.GLOBAL.equals(bo.getType())) {
                        result = new RegionAndPriceResult();
                        result.setConditionId(bo.getConditionId());
                        result.setId(bo.getId());
                        result.setPrice(bo.getPrice());
                        result.setType(bo.getType());
                        result.setInclude(bo.getInclude());
                        result.setRegion(JSON.parseArray(bo.getRegion(), Region.class));
                        includeList.add(result);
                    } else {
                        logger.info("AdPublishConditionController loadDetail() -> transferRegionAndPriceObject : 不匹配！");
                    }
                }

            }

        }
        o.setExclude(excludeList);
        o.setInclude(includeList);
        return o;
    }


	@Override
	public AdPublishConditionDetailResult getAdPublishConditionDetailResult(String userId, Long connObjId,
			String platform) {
		AdPublishCondition con = adPublishConditionRdbService.findAdPublishCondition(userId, connObjId, platform);
        return this.getAdPublishConditionDetailResult(con);
	}

    @Override
    public List<UserConnectionPage> findPageIdsByUserId(String userId) {
        return adPublishConditionRdbService.findPageIdsByUserId(userId);
    }
}
